package com.itmayiedu.aop;

import com.itmayiedu.JDBCutil.MyJDBC.Jdbcimpl.Insect;
import com.itmayiedu.JDBCutil.MyJDBC.Jdbcimpl.Select;
import com.itmayiedu.annotation.ExtInsert;
import com.itmayiedu.annotation.ExtMapper;
import com.itmayiedu.annotation.ExtParam;
import com.itmayiedu.annotation.ExtSelect;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 使用JDK代理模式，拦截接口的方法
 */
public class MyInvocationHandlerMbatis implements InvocationHandler {
    private Object subject;
    private static Class[] classes;
    {
        classes= new Class[]{ExtSelect.class, ExtInsert.class, ExtParam.class, ExtMapper.class};
    }
    public MyInvocationHandlerMbatis(Object subject){
        this.subject=subject;
    }

    /**
     *
     * @param proxy  代理对象
     * @param method  method拦截方法
     * @param args  args方法上的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Myfilter myfilter=new Myfilter();
        conditionInvoke(proxy,method,args,classes,myfilter);
        return 1;
    }


    /**
     * 策略者模式的使用
     * @param proxy 对象
     * @param method 对象的方法
     * @param args 方法的参数
     * @return
     */
    private void conditionInvoke(Object proxy, Method method, Object[] args,Class[] classes,Myfilter myfilter){
        for (int i = 0; i <classes.length ; i++) {
            Myworkingpool(classes[i],proxy,method,args,myfilter);
        }
    }

    private void  Myworkingpool(Class<?> Myclass,Object proxy, Method method, Object[] args, Myfilter myfilter){
        ExecutorService executorService= Executors.newFixedThreadPool(5);
        executorService.submit(new MyRunnable(Myclass,method,args,myfilter));
    }

    class MyRunnable implements Callable {
        private Class<?> Myclass;
        private Method method;
        private Object[] args;
        private Myfilter myfilter;
        public MyRunnable(Class<?> Myclass,Method method, Object[] args,Myfilter myfilter) {
            this.Myclass=Myclass;
            this.args=args;
            this.method=method;
            this.myfilter=myfilter;
        }

        /**
         * 策略者模式，不同的class类执行不同的代码逻辑
         * @return
         * @throws Exception
         */
        @Override
        public Object call() throws Exception {
            if (Myclass.isAssignableFrom(ExtInsert.class)){
                AtomicInteger i=new AtomicInteger();
                Insect insect=new Insect(method,args,i);
                Arrays.stream(method.getDeclaredAnnotations()).filter(myfilter::the).forEach(insect::Jdbcs);
                return i;
            }
            if (Myclass.isAssignableFrom(ExtMapper.class)){
                return null;
            }
            if (Myclass.isAssignableFrom(ExtParam.class)){
                return null;
            }
            if (Myclass.isAssignableFrom(ExtSelect.class)){
                Select select=new Select(method,args);
                Object[] objects = Arrays.stream(method.getDeclaredAnnotations()).filter(myfilter::the).toArray();
                for (int i = 0; i < objects.length; i++) {
                   return select.Jdbcs((Annotation)objects[i]);
                }
                return null;
            }
            return null;
        }
    }

}
